/* 
*  Copyright (C) 2009-2010 WCG Project
*
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*/


new const Float:p_evasion[5]	= {0.02, 0.04, 0.06, 0.08, 0.10}		// Evasion
new const Float:p_sprint[5]		= {7.0, 14.0, 21.0, 28.0, 35.0}			// Sprint
new const Float:p_levitation[5]	= {0.8, 0.7, 0.6, 0.5, 0.4}				// Levitation
new const Float:p_cheatdeath[5]	= {0.08, 0.16, 0.24, 0.32, 0.40}		// Cheat Death
new const Float:p_ambush[5]		= {1.20, 1.40, 1.60, 1.80, 2.00}		// ambush

static Float:g_fLastStealthActivateTime[33]


ROGUE_InitSkills()
{
	SM_InitSkill( SKILL_EVASION, CLASS_ROGUE, SKILL_TYPE_TRAINABLE, sizeof(p_evasion) )
	SM_InitSkill( SKILL_SPRINT, CLASS_ROGUE, SKILL_TYPE_TRAINABLE, sizeof(p_sprint) )
	SM_InitSkill( SKILL_LEVITATION, CLASS_ROGUE, SKILL_TYPE_TRAINABLE, sizeof(p_levitation) )
	SM_InitSkill( SKILL_AMBUSH, CLASS_ROGUE, SKILL_TYPE_TRAINABLE, sizeof(p_ambush), 10, _, ULTIMATE_STEALTH )
	SM_InitSkill( SKILL_CHEATDEATH, CLASS_ROGUE, SKILL_TYPE_TRAINABLE, sizeof(p_cheatdeath), 20, 60 )
	SM_InitSkill( ULTIMATE_STEALTH, CLASS_ROGUE, SKILL_TYPE_ULTIMATE, 5, 10, 10 )
}


/*
//------------------------------------
// ROGUE_TriggerAbility
//
//------------------------------------
ROGUE_TriggerAbility( id, iSkillID )
{

}
*/


//------------------------------------
// ROGUE_TriggerUltimate
//
//------------------------------------
ROGUE_TriggerUltimate( id, iSkillID )
{
	if( iSkillID == ULTIMATE_STEALTH )
	{
		if( PlayerInfo[id][PI_Stealthed] )
		{
			if( get_gametime() - g_fLastStealthActivateTime[id] > 1.0 )
				_RemoveStealth( id )

			return
		}

		new param[2]
		param[0] = id
		param[1] = SM_GetSkillLevel( id, iSkillID )
		PLAYER_CastSpell( id, ULTIMATE_STEALTH, CAST_NORMAL, "_SPELL_Stealth", param, 2, CAST_SKIP_ENDCAST_SOUND )
	}
}


//------------------------------------
// ROGUE_Heartbeat
//
// This will only be called while the player is alive and freezetime is false
//------------------------------------
public ROGUE_Heartbeat( id )
{
	static Float:vOrigin[3], Float:bOrigin[3]

	if( GameInfo[GI_BombPlanted] == true )
	{
		bOrigin[0] = GameInfo[GI_BombOrigin+S_GAMEINFO:0]
		bOrigin[1] = GameInfo[GI_BombOrigin+S_GAMEINFO:1]
		bOrigin[2] = GameInfo[GI_BombOrigin+S_GAMEINFO:2]

		for( id = 1 ; id <= GameInfo[GI_MaxPlayers] ; id++ )
		{
			if( PlayerInfo[id][PI_Class] != CLASS_ROGUE )
				continue

			if( PlayerInfo[id][PI_Stealthed] == 0 )
				continue

			pev( id, pev_origin, vOrigin )
			
			if( get_distance_f( vOrigin, bOrigin ) < 600.0 )
			{
				client_print( id, print_chat, "You are unable to stealth near the bomb...")
				_RemoveStealth( id )
			}
		}
	}
}



//------------------------------------
// ROGUE_SkillsDefensive
//
//------------------------------------
public ROGUE_SkillsDefensive( iAttacker, iVictim, &iDamage, iWeapon, iDamageType )
{
	static iSkillLevel

	iSkillLevel = SM_GetSkillLevel( iVictim, SKILL_CHEATDEATH )
	if( iSkillLevel > 0 )
		ROGUE_CheatDeath( iSkillLevel, iVictim, iDamage )
}


//------------------------------------
// ROGUE_SkillsOffensive
//
//------------------------------------
public ROGUE_SkillsOffensive( iAttacker, iVictim, iWeapon, &iDamage, iDamageType )
{
	if( PlayerInfo[iAttacker][PI_Stealthed] )
	{
		if( (iDamageType & DMG_SLASH) && (PlayerInfo[iAttacker][PI_KnifeAttackType] == 2) )
		{
			new iSkillLevel = SM_GetSkillLevel( iAttacker, SKILL_AMBUSH )
			if( iSkillLevel > 0 )
			{
				static Float:fVictimAngle[3], Float:fAttackerAngle[3], Float:fAngle

				pev( iVictim, pev_v_angle, fVictimAngle )
				pev( iAttacker, pev_v_angle, fAttackerAngle )

				fAngle = fAttackerAngle[1] -= fVictimAngle[1]
				if( fAngle >= -45.0 && fAngle <= 45.0 )
				{
					iDamage = floatround( float(iDamage) * p_ambush[iSkillLevel-1] )
//					emit_sound( iVictim, CHAN_STATIC, g_szSounds[SOUND_AMBUSH], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )
					emit_sound( iVictim, CHAN_STATIC, g_szSounds[SOUND_STRIKE], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )
				}
			}
		}

		_RemoveStealth( iAttacker )
	}
}


//--------------------------------------------------------------------------------------------------------------------------
// Evasion


//------------------------------------
// ROGUE_Evasion
//
//------------------------------------
bool:ROGUE_Evasion( iVictim, iHitgroup )
{
	new iSkillLevel = SM_GetSkillLevel( iVictim, SKILL_EVASION )
	
	if( iSkillLevel > 0 && random_float( 0.0, 1.0 ) <= p_evasion[iSkillLevel-1] )
	{
		new iGlowIntensity = random_num( 20, 50 )
		
		// Head shot
		if( iHitgroup == HIT_HEAD )
			iGlowIntensity += 250
		else if( iHitgroup == HIT_CHEST )
			iGlowIntensity += 75
		
		// Make the user glow!
		SHARED_Glow( iVictim, COLOR_RGB( 0, 0, iGlowIntensity ) )

		EFFECT_ScreenFade( iVictim, 0.25, 0.25, COLOR_RGBA(0, 0, 255, min(iGlowIntensity, 150)) )

		WCG_StatusText( iVictim, TXT_SKILL, HUD_SKILL, "You have evaded a shot!" )
		return true
	}
	return false
}


//--------------------------------------------------------------------------------------------------------------------------
// Cheat Death


//------------------------------------
// ROGUE_CheatDeath
//
//------------------------------------
ROGUE_CheatDeath( iSkillLevel, iVictim, &iDamage )
{
	new Float:fHealth, Float:fCurrentArmor, Float:fNewDamage, Float:fArmorLost
	new Float:fDamage = float( iDamage )

	if( PlayerInfo[iVictim][PI_IsCheatDeathActive] )
	{
		iDamage = floatround( fDamage * 0.03, floatround_ceil )
		iDamage = max( iDamage, 1 )
		return
	}

	if( SM_IsOnCooldown( iVictim, SKILL_CHEATDEATH ) )
		return
	
	if( random_float( 0.0, 1.0 ) > p_cheatdeath[iSkillLevel-1] )
		return

	pev( iVictim, pev_health, fHealth )
	pev( iVictim, pev_armorvalue, fCurrentArmor )

	fNewDamage = fDamage * ARMOR_RATIO
	fArmorLost = ( fDamage - fNewDamage ) * ARMOR_BONUS

	if( fArmorLost > fCurrentArmor )
	{
		fArmorLost = fCurrentArmor * (1/ARMOR_BONUS)
		fNewDamage = fDamage - fArmorLost
	}

	if( fNewDamage >= fHealth )
	{
		PlayerInfo[iVictim][PI_IsCheatDeathActive] = true
		SM_SetCooldown( iVictim, SKILL_CHEATDEATH )
		set_task( 2.0, "_ROGUE_RemoveCheatDeath", TASK_ALIVE_EFFECT + iVictim )

		fHealth = float( PLAYER_GetMaxhealth( iVictim ) )
		
		set_pev( iVictim, pev_health, fHealth * 0.10 )
		cs_set_user_armor( iVictim, 0, CS_ARMOR_NONE )

		if( PlayerInfo[iVictim][PI_Stealthed] > 0 )
			_RemoveStealth( iVictim )

		if( PlayerInfo[iVictim][PI_CanRender] )
			fm_set_user_rendering( iVictim, kRenderFxGlowShell, 255, 30, 0, kRenderNormal, 18 )

		static vOrigin[3]

		get_user_origin( iVictim, vOrigin )
		vOrigin[2] += 75
		
		Create_TE_ELIGHT( iVictim, vOrigin, 100, 255, 30, 0, 2, 0 )

		EFFECT_ScreenFade( iVictim, 0.25, 0.25, COLOR_RGBA(255, 0, 0, 96) )

		emit_sound( iVictim, CHAN_STATIC, g_szSounds[SOUND_STRIKE], VOL_NORM, ATTN_NORM, 0, PITCH_NORM )

		iDamage = 0
	}
}


//------------------------------------
// _ROGUE_RemoveCheatDeath
//
//------------------------------------
public _ROGUE_RemoveCheatDeath( id )
{
	id = GetTaskID( id, TASK_ALIVE_EFFECT )

	PlayerInfo[id][PI_IsCheatDeathActive] = false

	PLAYER_UpdateInvisibility( id )
}



//--------------------------------------------------------------------------------------------------------------------------
// Stealth

#define STEALTH_TIME 10


//------------------------------------
// _SPELL_Stealth
//
// PLAYER_CastSpell callback
//		param[0] = Caster ID
//		param[1] = Skill level
//------------------------------------
public _SPELL_Stealth( param[] )
{
	new id = param[0]
	new iSkillLevel = param[1]

	if( iSkillLevel <= 0 )
		return

	PlayerInfo[id][PI_Stealthed] = iSkillLevel

	emit_sound( id, CHAN_STATIC, g_szSounds[SOUND_STEALTH], 0.7, ATTN_NORM, 0, PITCH_NORM )

	PLAYER_UpdateSpeed( id )
	PLAYER_UpdateInvisibility( id )

	PlayerInfo[id][PI_CanRender] = false

	ULT_Icon( id, ICON_FLASH )

	Create_BarTime( id, STEALTH_TIME, 0 )

	engclient_cmd( id, "weapon_knife" )

	set_task( 0.2, "_StealthCheck", TASK_STEALTH + id )
	set_task( float(STEALTH_TIME), "_RemoveStealth", TASK_STEALTH + id )

	g_fLastStealthActivateTime[id] = get_gametime()
}

public _StealthCheck( id )
{
	id = GetTaskID( id, TASK_STEALTH )

	if( !is_user_alive( id ) )
		return

	if( PlayerInfo[id][PI_Stealthed] > 0 )
		PLAYER_UpdateInvisibility( id )
	
	set_task( 0.2, "_StealthCheck", TASK_STEALTH + id )
}

public _RemoveStealth( id )
{
	id = GetTaskID( id, TASK_STEALTH )

	// Re-set the cooldown since we want it to start when the player leaves stealth mode
	SM_SetCooldown( id, ULTIMATE_STEALTH )

	if( PlayerInfo[id][PI_Stealthed] )
	{
		WCG_StatusText( id, 0, HUD_CASTING, "You are no longer stealthed" )
		client_cmd( id, "spk buttons/blip2.wav" )
		EFFECT_ScreenFade( id, 0.10, 0.25, COLOR_RGBA(0, 128, 255, 128) )
	}

	PlayerInfo[id][PI_Stealthed] = 0
	PlayerInfo[id][PI_CanRender] = true

	// Don't remove bar if player has started planting or defusing the bomb
	if( !PlayerInfo[id][PI_IsPlantingDefusing] )
		Create_BarTime( id, 0, 0 )

	ULT_ClearIcons( id )

	PLAYER_UpdateSpeed( id )
	PLAYER_UpdateInvisibility( id )

	remove_task( TASK_STEALTH + id )
}
